/******************************************************************************/
/*                                                                            */
/*  Copyright (c) 2009: ngi-central.org                                       */
/*  All rights reserved.                                                      */
/*                                                                            */
/******************************************************************************/


#include <boost/test/unit_test.hpp>

#include "..\..\include\sgl\point.h"
#include "..\..\include\sgl\vector.h"

BOOST_AUTO_TEST_SUITE( point3d )


BOOST_AUTO_TEST_CASE( point3d__default_constructor )
{
	sgl::point<3> a;

	BOOST_CHECK( a[0] == 0 );
	BOOST_CHECK( a[1] == 0 );
	BOOST_CHECK( a[2] == 0 );


	sgl::point<3> b(1, 2, 3);

	BOOST_CHECK( b[0] == 1 );
	BOOST_CHECK( b[1] == 2 );
	BOOST_CHECK( b[2] == 3 );
}

BOOST_AUTO_TEST_CASE( point3d__copy_constructor )
{
	sgl::point<3> a(sgl::point<3>(1, 2, 3));

	BOOST_CHECK( a[0] == 1 );
	BOOST_CHECK( a[1] == 2 );
	BOOST_CHECK( a[2] == 3 );
}

BOOST_AUTO_TEST_CASE( point3d__copy_assignment )
{
	sgl::point<3> a;
	a = sgl::point<3>(1, 2, 3);

	BOOST_CHECK( a[0] == 1 );
	BOOST_CHECK( a[1] == 2 );
	BOOST_CHECK( a[2] == 3 );
}

BOOST_AUTO_TEST_CASE( point3d__swap )
{
	sgl::point<3> a(1, 2, 3);
	sgl::point<3> b(4, 5, 6);

	a.swap(b);

	BOOST_CHECK( a[0] == 4 );
	BOOST_CHECK( a[1] == 5 );
	BOOST_CHECK( a[2] == 6 );
	BOOST_CHECK( b[0] == 1 );
	BOOST_CHECK( b[1] == 2 );
	BOOST_CHECK( b[2] == 3 );

	b.swap(a);

	BOOST_CHECK( a[0] == 1 );
	BOOST_CHECK( a[1] == 2 );
	BOOST_CHECK( a[2] == 3 );
	BOOST_CHECK( b[0] == 4 );
	BOOST_CHECK( b[1] == 5 );
	BOOST_CHECK( b[2] == 6 );
}

BOOST_AUTO_TEST_CASE( point3d__operator_square_brackets )
{
	sgl::point<3> a;

	BOOST_CHECK_THROW( a[-1], sgl::precondition_violated );
	BOOST_CHECK( a[0] == 0 );
	BOOST_CHECK( a[1] == 0 );
	BOOST_CHECK( a[2] == 0 );
	BOOST_CHECK_THROW( a[3], sgl::precondition_violated );

	a[0] = 1;
	a[1] = 2;
	a[2] = 3;

	BOOST_CHECK( a[0] == 1 );
	BOOST_CHECK( a[1] == 2 );
	BOOST_CHECK( a[2] == 3 );

	sgl::point<3> const b;

	BOOST_CHECK_THROW( b[-1], sgl::precondition_violated );
	BOOST_CHECK( b[0] == 0 );
	BOOST_CHECK( b[1] == 0 );
	BOOST_CHECK( b[2] == 0 );
	BOOST_CHECK_THROW( b[3], sgl::precondition_violated );
}

BOOST_AUTO_TEST_CASE( point3d__x )
{
	sgl::point<3> a;

	BOOST_CHECK( a.x() == 0 );

	a[0] = 1;

	BOOST_CHECK( a.x() == 1 );

	sgl::point<3> const b;

	BOOST_CHECK( b.x() == 0 );
}

BOOST_AUTO_TEST_CASE( point3d__y )
{
	sgl::point<3> a;

	BOOST_CHECK( a.y() == 0 );

	a[1] = 2;

	BOOST_CHECK( a.y() == 2 );

	sgl::point<3> const b;

	BOOST_CHECK( b.y() == 0 );
}

BOOST_AUTO_TEST_CASE( point3d__z )
{
	sgl::point<3> a;

	BOOST_CHECK( a.z() == 0 );

	a[2] = 3;

	BOOST_CHECK( a.z() == 3 );

	sgl::point<3> const b;

	BOOST_CHECK( b.z() == 0 );
}

BOOST_AUTO_TEST_CASE( point3d__geometric_type )
{
	sgl::point<3> a;

	BOOST_CHECK( a.type() == sgl::geometric_primitive<>::point );
}

BOOST_AUTO_TEST_CASE( point3d__dimensions )
{
	sgl::point<3> a;

	BOOST_CHECK( a.dimensions() == 3 );
}

BOOST_AUTO_TEST_CASE( point3d__operator_minus )
{
	sgl::point<3> a(1, 2, 3);
	sgl::point<3> b = -a;

	BOOST_CHECK( a[0] == 1 );
	BOOST_CHECK( a[1] == 2 );
	BOOST_CHECK( a[2] == 3 );
	BOOST_CHECK( b[0] == -1 );
	BOOST_CHECK( b[1] == -2 );
	BOOST_CHECK( b[2] == -3 );
}

BOOST_AUTO_TEST_CASE( point3d__operator_equality )
{
	sgl::point<3> a;
	sgl::point<3> b;

	BOOST_CHECK( a == b );

	sgl::point<3> c(1, 2, 3);
	sgl::point<3> d(1, 2, 3);

	BOOST_CHECK( c == d );
}

BOOST_AUTO_TEST_CASE( point3d__operator_inequality )
{
	sgl::point<3> a;
	sgl::point<3> b(1, 2, 3);

	BOOST_CHECK( a != b );

	sgl::point<3> c;
	sgl::point<3> d(1, 2, 3);

	BOOST_CHECK( c != d );
}

BOOST_AUTO_TEST_CASE( point3d__addition )
{
	sgl::point<3> a;
	a += sgl::vector<3>(1, 2, 3);

	BOOST_CHECK( a[0] == 1 );
	BOOST_CHECK( a[1] == 2 );
	BOOST_CHECK( a[2] == 3 );

	sgl::point<3> b(1, 2, 3);
	sgl::vector<3> c(4, 5, 6);
	sgl::point<3> d = b+c;

	BOOST_CHECK( d[0] == 5 );
	BOOST_CHECK( d[1] == 7 );
	BOOST_CHECK( d[2] == 9 );

	sgl::point<3> e = c+b;

	BOOST_CHECK( e[0] == 5 );
	BOOST_CHECK( e[1] == 7 );
	BOOST_CHECK( e[2] == 9 );
}

BOOST_AUTO_TEST_CASE( point3d__subtraction )
{
	sgl::point<3> a;
	a -= sgl::vector<3>(1, 2, 3);

	BOOST_CHECK( a[0] == -1 );
	BOOST_CHECK( a[1] == -2 );
	BOOST_CHECK( a[2] == -3 );

	sgl::point<3> b(1, 2, 3);
	sgl::point<3> c(4, 5, 6);
	sgl::vector<3> d = b-c;

	BOOST_CHECK( d[0] == -3 );
	BOOST_CHECK( d[1] == -3 );
	BOOST_CHECK( d[2] == -3 );

	sgl::vector<3> e = c-b;

	BOOST_CHECK( e[0] == 3 );
	BOOST_CHECK( e[1] == 3 );
	BOOST_CHECK( e[2] == 3 );
}

BOOST_AUTO_TEST_CASE( point3d__scale_multiply )
{
	sgl::point<3> a(1, 2, 3);
	a *= 2;

	BOOST_CHECK( a[0] == 2 );
	BOOST_CHECK( a[1] == 4 );
	BOOST_CHECK( a[2] == 6 );

	sgl::point<3> b(1, 2, 3);
	sgl::point<3> c = b*2;

	BOOST_CHECK( c[0] == 2 );
	BOOST_CHECK( c[1] == 4 );
	BOOST_CHECK( c[2] == 6 );

	sgl::point<3> d = 2*b;

	BOOST_CHECK( d[0] == 2 );
	BOOST_CHECK( d[1] == 4 );
	BOOST_CHECK( d[2] == 6 );
}

BOOST_AUTO_TEST_CASE( point3d__scale_divide )
{
	sgl::point<3> a(2, 4, 6);
	a /= 2;

	BOOST_CHECK( a[0] == 1 );
	BOOST_CHECK( a[1] == 2 );
	BOOST_CHECK( a[2] == 3 );

	sgl::point<3> b(2, 4, 6);
	sgl::point<3> c = b/2;

	BOOST_CHECK( c[0] == 1 );
	BOOST_CHECK( c[1] == 2 );
	BOOST_CHECK( c[2] == 3 );
}


BOOST_AUTO_TEST_SUITE_END()

